/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 * */

// AmzServer - Tototoy's server model.
// Author: tonyjobmails@gmail.com (tonyhack).
//
// Define class TestThread.
//

#include "ring_queue_single_model_boundless.h"
#include "test_thread.h"
#include "logging.h"

namespace amz {

TestThread::TestThread(RingQueueInterface *communication,
       uint8 type, std::string name, bool joinable)
	   : Thread(name, joinable), type_(type), total_(0) {
  if(communication) {
    this->communication_ = communication;
  } else {
    LOG(ERROR) << "Error, communication is a null value!";
  }
}

TestThread::~TestThread() {
}
  
void TestThread::Run() {
  int pos = 0;
  
  while(pos++ < 1000) {

    this->Sleep(1);
    if(this->type_ == TEST_THREAD_TYPE_CLIENT) {
      char buffer[kTestThreadUnitMaxSize];
      while(true) {
        int32 buffer_size = this->communication_->Remove(buffer,
	      kTestThreadUnitMaxSize);
	if(buffer_size == -1) {
          g_test_thread_mutex.Lock();
	  LOG(ERROR) << "Error in Remove.";
	  g_test_thread_mutex.Unlock();
          break;
        } else if(buffer_size == 0) {
	  g_test_thread_mutex.Lock();
	  LOG(INFO) << "Read complete.";
	  g_test_thread_mutex.Unlock();
          pos += 2;
	  this->Sleep(13);
	  break;
	} else {
          buffer[buffer_size] = '\0';
	  g_test_thread_mutex.Lock();
	  LOG(INFO) << "Read size="
                    << buffer_size
                    << ", data=\""
                    << buffer
                    << "\"";
	  g_test_thread_mutex.Unlock();
          ++this->total_;
	}
      }

    } else {

      while(pos++ < 2500) {
        if(pos > 1600) {
          this->communication_->Flush();
          this->Sleep(3);
          continue;
        }
        std::string data;
        switch(pos % 10){
	  case 0: {
            this->communication_->Flush();
            this->Sleep(9);
            continue;
	    break;
	  }
	  case 1: {
	    data = "111";
	    break;
          }
	  case 2: {
	    data = "2222222";
	    break;
	  }
	  case 3: {
	    data = "3333333333333333333333";
	    break;
	  }
	  case 4: {
	    data = "4444444444444444";
	    break;
	  }
	  case 5: {
	    data = "555555555555555555555555555555";
	    break;
	  }
	  case 6: {
	    data = "666666666666666666666666666666666";
	    break;
	  }
	  case 7: {
	    data = "7777777777777777777777777";
	    break;
	  }
	  case 8: {
	    data = "888888888888";
	    break;
	  }
	  case 9: {
	    data = "999999999999999999999999999999999999999999999";
	    break;
	  }
	}
        uint32 size = this->communication_->Add(data.c_str(), data.length());
	if(size <= 0) {
	  g_test_thread_mutex.Lock();
	  LOG(ERROR) << "Write error.";
	  g_test_thread_mutex.Unlock();
	} else {
	  g_test_thread_mutex.Lock();
	  LOG(INFO) << "Write size="
                    << data.length()
                    << ", data=\""
                    << data
                    << "\"";
          g_test_thread_mutex.Unlock();
          ++this->total_;
          this->Sleep(2);
	}
      }
    }
  }
}

}  // namespace amz


using namespace amz;

int main() {
  InitializeLogger("/tmp/info.log", "/tmp/warn.log", "/tmp/erro.log");

  RingQueueSingleModelBoundless *ring_queue = new RingQueueSingleModelBoundless(128, 64, false);

  TestThread server(ring_queue, TEST_THREAD_TYPE_CLIENT, "TestThreadServer", true);
  server.Start();

  TestThread client(ring_queue, TEST_THREAD_TYPE_SERVER, "TestThreadClient", true);
  client.Start();

  server.Join();
  client.Join();

  LOG(INFO) << "Summary: "
            << "server receive=\"" << server.GetTotal() << "\", "
            << "client send=\"" << client.GetTotal() << "\"";

  
}
